import 'package:flutter/material.dart';
import './fab.dart';
import 'dart:math' as math;

class FabMenu extends StatefulWidget {
  final Widget child;
  final double right;
  final double bottom;
  final double size;
  final Color color;
  final List<FabMenuItem> list;

  FabMenu({
    Key? key,
    required this.child,
    this.right = 30,
    this.bottom = 30,
    this.size = 50,
    this.color = Colors.blue,
    this.list = const [],
  }) : super(key: key);

  @override
  _FabFabMenuState createState() => _FabFabMenuState();
}

class _FabFabMenuState extends State<FabMenu> {
  OverlayEntry? _fab;

  GlobalKey<_FabMenuButtonState> _key = GlobalKey<_FabMenuButtonState>();

  _fabBuilder() {
    _fab?.remove();

    _fab = OverlayEntry(
      builder: (BuildContext context) {
        return FabPositioned(
          right: widget.right,
          bottom: widget.bottom,
          size: widget.size,
          child: FabMenuButton(
            key: _key,
            size: widget.size,
            color: widget.color,
            list: widget.list,
          ),
        );
      },
    );

    Overlay.of(context)!.insert(_fab!);
  }

  @override
  void initState() {
    super.initState();

    WidgetsBinding.instance!.addPostFrameCallback((_) {
      _fabBuilder();
    });
  }

  @override
  void dispose() {
    _fab?.remove();
    super.dispose();
  }

  @override
  void didUpdateWidget(covariant FabMenu oldWidget) {
    super.didUpdateWidget(oldWidget);
    // 更新按钮菜单列表
    WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
      _key.currentState!.setList(widget.list);
    });
  }

  @override
  Widget build(BuildContext context) {
    return widget.child;
  }
}

// 菜单拖动定位
class FabPositioned extends StatefulWidget {
  final Widget child;
  final double right;
  final double bottom;
  final double size;

  FabPositioned({
    Key? key,
    required this.child,
    this.right = 30,
    this.bottom = 30,
    this.size = 50,
  }) : super(key: key);

  @override
  _FabPositionedState createState() => _FabPositionedState();
}

class _FabPositionedState extends State<FabPositioned> {
  Offset _position = Offset.zero;

  GlobalKey _key = GlobalKey();

  late Offset _initOffset;

  @override
  void initState() {
    super.initState();

    // 获取初始定位
    WidgetsBinding.instance!.addPostFrameCallback((_) {
      RenderBox renderObject =
          _key.currentContext!.findRenderObject()! as RenderBox;
      _initOffset = renderObject.localToGlobal(Offset.zero);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Positioned(
      right: widget.right + _position.dx,
      bottom: widget.bottom + _position.dy,
      child: GestureDetector(
        key: _key,
        onPanUpdate: (DragUpdateDetails details) {
          setState(() {
            _position = Offset(
              _initOffset.dx - details.globalPosition.dx + widget.size / 2,
              _initOffset.dy - details.globalPosition.dy + widget.size / 2,
            );
          });
        },
        child: widget.child,
      ),
    );
  }
}

// 单个菜单
class FabMenuItem {
  IconData icon;
  String? text;
  Color? color;
  Function? onTap;

  FabMenuItem({
    required this.icon,
    this.text,
    this.color,
    this.onTap,
  });
}

// 菜单样式
class FabMenuButton extends StatefulWidget {
  final double size;
  final Color color;
  final List<FabMenuItem> list;

  FabMenuButton({
    Key? key,
    this.size = 50,
    this.color = Colors.blue,
    this.list = const [],
  }) : super(key: key);

  @override
  _FabMenuButtonState createState() => _FabMenuButtonState();
}

class _FabMenuButtonState extends State<FabMenuButton>
    with TickerProviderStateMixin {
  List<FabMenuItem> _list = [];

  late AnimationController _controller;

  Animation<double>? _heightAnimation;

  double _endHeight = 0;

  Animation<double>? _rotateAnimation;

  double _endRotate = math.pi / 4;

  GlobalKey _key = GlobalKey();

  // 设置按钮列表
  setList(List<FabMenuItem> list) {
    setState(() {
      _list = list;
    });
  }

  // 切换
  void _toggle() {
    if (_controller.status == AnimationStatus.dismissed ||
        _controller.status == AnimationStatus.reverse) {
      _controller.forward();
    } else {
      _controller.reverse();
    }
  }

  // 单个按钮
  Widget _itemBuilder(int index) {
    FabMenuItem item = _list[index];

    return Container(
      width: widget.size,
      // height: widget.size,
      padding: EdgeInsets.symmetric(vertical: 10),
      child: GestureDetector(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Icon(
              item.icon,
              size: 24,
              color: item.color ?? Colors.grey,
            ),
            item.text != null && item.text!.isNotEmpty
                ? Text(
                    item.text!,
                    style: TextStyle(
                      fontSize: 11,
                      fontWeight: FontWeight.w400,
                      color: item.color ?? Colors.grey,
                      decoration: TextDecoration.none,
                    ),
                  )
                : SizedBox(),
          ],
        ),
        onTap: () {
          if (item.onTap != null) {
            item.onTap!();
          }
        },
      ),
    );
  }

  @override
  void initState() {
    super.initState();

    _list = widget.list;

    _controller = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 200),
    );

    WidgetsBinding.instance!.addPostFrameCallback((_) {
      RenderObject renderObject = _key.currentContext!.findRenderObject()!;
      Rect rect = renderObject.semanticBounds;

      _endHeight = rect.height;

      _heightAnimation = Tween<double>(
        begin: widget.size,
        end: _endHeight,
      ).animate(_controller);

      _rotateAnimation = Tween<double>(
        begin: 0,
        end: _endRotate,
      ).animate(_controller);

      _controller.addListener(() {
        setState(() {});
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      alignment: Alignment.bottomCenter,
      children: [
        Container(
          width: widget.size,
          height: _heightAnimation?.value ?? widget.size,
          decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.circular(widget.size),
            boxShadow: <BoxShadow>[
              BoxShadow(
                color: Color.fromRGBO(136, 136, 136, 0.1),
                blurRadius: 20,
                spreadRadius: 5,
              ),
            ],
          ),
          child: ClipRRect(
            borderRadius: BorderRadius.circular(widget.size),
            child: SingleChildScrollView(
              physics: NeverScrollableScrollPhysics(),
              child: Container(
                key: _key,
                alignment: Alignment.topCenter,
                child: Column(
                  children: [
                    SizedBox(
                      height: 10,
                    ),
                    ...List.generate(
                      widget.list.length,
                      (index) => _itemBuilder(index),
                    ),
                    SizedBox(
                      width: widget.size,
                      height: widget.size,
                    ),
                  ],
                ),
              ),
            ),
          ),
        ),
        Transform.rotate(
          angle: _rotateAnimation?.value ?? 0,
          child: FabButton(
            size: widget.size,
            color: widget.color,
            icon: Icons.add,
            isShadow: false,
            onTap: _toggle,
          ),
        ),
      ],
    );
  }
}
